using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Text.RegularExpressions;
using System.Xml.Serialization;
using CodePlex.DnD4eCampaignManager.DnD4e.Interfaces;

namespace CodePlex.DnD4eCampaignManager.Repositories.XmlRepositories
{
    public abstract class BaseXmlRepository<T> where T : class, IPersistable
    {
        private static readonly Random _random = new Random();
        protected abstract string Extension { get; }
        protected abstract string Folder { get; }
        protected abstract XmlSerializer XmlSerializer { get; }

        public ReadOnlyCollection<string> GetAllNames()
        {
            List<string> fileNames = new List<string>();
            foreach ( string fileName in Directory.GetFiles(Folder, string.Format("*{0}", Extension)) )
            {
                string fileNameWithExtensionAndFolderRemoved = GetFileNameWithExtensionAndFolderRemoved(fileName);
                if ( !string.IsNullOrEmpty(fileNameWithExtensionAndFolderRemoved) )
                {
                    fileNames.Add(fileNameWithExtensionAndFolderRemoved);
                }
            }
            return fileNames.AsReadOnly();
        }

        public T GetByName(string fileName)
        {
            string filePath = string.Format("{1}\\{0}{2}", fileName, Folder, Extension);
            if ( File.Exists(filePath) )
            {
                using ( TextReader textReader = new StreamReader(filePath) )
                {
                    try
                    {
                        T domainObject = XmlSerializer.Deserialize(textReader) as T;
                        IInitiative domainObjectInitiative = domainObject as IInitiative;
                        if ( domainObjectInitiative != null )
                        {
                            domainObjectInitiative.InitiativeScore = _random.Next(1, 20);
                        }
                        return domainObject;
                    }
                    catch ( Exception )
                    {
                        return null;
                    }
                }
            }
            return null;
        }

        public void Save(T domainObject)
        {
            if ( string.IsNullOrEmpty(domainObject.Name) )
            {
                return;
            }
            using ( TextWriter textWriter = new StreamWriter(string.Format("{1}\\{0}{2}", domainObject.Name, Folder, Extension)) )
            {
                XmlSerializer.Serialize(textWriter, domainObject);
            }
        }

        protected void InitializeRepository()
        {
            if ( !Directory.Exists(Folder) )
            {
                Directory.CreateDirectory(Folder);
            }
        }

        private string GetFileNameWithExtensionAndFolderRemoved(string fileName)
        {
            const RegexOptions regexOptions = RegexOptions.IgnoreCase;
            string fileNameAfterExtensionIsRemoved = Regex.Replace(fileName, string.Format("{0}$", Extension), string.Empty, regexOptions);
            string fileNameAfterFolderRemoved = Regex.Replace(fileNameAfterExtensionIsRemoved, string.Format("^{0}", Folder), string.Empty,
                                                              regexOptions);
            string fileNameAfterAllCleanUp = Regex.Replace(fileNameAfterFolderRemoved, @"\\", string.Empty, regexOptions);
            return fileNameAfterAllCleanUp;
        }
    }
}